package com.google.jessewilson.codesearch.googlecodesearch;

import org.ccil.cowan.tagsoup.Parser;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

/**
 * Convert HTML to code by stripping the tags and converting entities to
 * their values.
 *
 * @author jessewilson
 */
class HtmlToCode extends DefaultHandler {

  private final Reader htmlIn;
  private final Writer codeOut;

  protected final List<String> tagStack = new ArrayList<String>();

  public HtmlToCode(Reader htmlIn, Writer codeOut) {
    this.htmlIn = htmlIn;
    this.codeOut = codeOut;
  }

  public void extractCode() throws IOException, SAXException {
    Parser parser = new Parser();
    parser.setContentHandler(this);
    parser.parse(new InputSource(htmlIn));
    codeOut.flush();
  }

  public void startElement(String uri, String localName, String qName,
      Attributes attributes) throws SAXException {
    tagStack.add(localName);
  }

  public void endElement(String uri, String localName, String qName)
      throws SAXException {
    assert(!tagStack.isEmpty());
    tagStack.remove(tagStack.size() - 1);
  }

  public void characters(char ch[], int start, int length)
      throws SAXException {
    if (withinCode()) {
      try {
        codeOut.write(ch, start, length);
      } catch (IOException e) {
        throw new SAXException(e);
      }
    }
  }

  protected boolean withinCode() {
    return true;
  }

  public void ignorableWhitespace(char ch[], int start, int length)
      throws SAXException {
    if (withinCode()) {
      try {
        codeOut.write(ch, start, length);
      } catch (IOException e) {
        throw new SAXException(e);
      }
    }
  }
}